

function getDecoratorProperties(path, t) {

    let paths = path.get('body.body');
    let properties, decorators;

    for (let i = paths.length; i--;)
    {
        let node = paths[i].node;

        if (!node.static && node.type === 'ClassProperty' && (decorators = node.decorators))
        {
            for (let j = decorators.length; j--;)
            {
                let expression = decorators[j].expression;

                switch (expression.type)
                {
                    case 'Identifier':
                        if (expression.name === 'p')
                        {
                            let property = t.objectProperty(node.key, node.value);

                            if (properties)
                            {
                                properties.push(property);
                            }
                            else
                            {
                                properties = [property];
                            }
                            
                            paths[i].remove();
                        }
                        break;

                    case 'CallExpression':
                        if (expression.callee.name === 'p')
                        {
                            let argument, property;

                            if (argument = expression.arguments[0])
                            {
                                if (argument.type === 'ObjectExpression')
                                {
                                    property = t.objectProperty(
                                        node.key, 
                                        t.objectExpression([
                                            t.objectProperty(
                                                t.identifier('defaultValue'), 
                                                node.value
                                            ),
                                            ...argument.properties
                                        ])
                                    );
                                }
                                else
                                {
                                    property = t.objectProperty(node.key, argument);
                                }
                            }
                            else
                            {
                                property = t.objectProperty(node.key, node.value);
                            }

                            if (properties)
                            {
                                properties.push(property);
                            }
                            else
                            {
                                properties = [property];
                            }
                            
                            paths[i].remove();
                        }
                        break;
                }
            }
        }
    }

    if (properties)
    {
        return t.objectExpression(properties);
    }
}




module.exports = function ({ types }, options) {

    
    return {
        
        name: 'babel-plugin-property',

        visitor: {


            ClassDeclaration(path) {

                let t = types;
                let properties;

                if (properties = getDecoratorProperties(path, t))
                {
                    path.insertAfter(t.expressionStatement(
                        t.callExpression(
                            t.memberExpression(
                                t.memberExpression(
                                    t.identifier('Object'),
                                    t.identifier('yaxi')
                                ),
                                t.identifier('propertiesDecorator'),
                            ),
                            [
                                t.identifier(path.node.id.name),
                                properties
                            ]
                        )
                    ));
                }
            },


            ClassExpression(path) {
                
                let t = types;
                let properties;

                if (properties = getDecoratorProperties(path, t))
                {
                    path.replaceWith(t.callExpression(
                        t.memberExpression(
                            t.memberExpression(
                                t.identifier('Object'),
                                t.identifier('yaxi')
                            ),
                            t.identifier('propertiesDecorator'),
                        ),
                        [
                            path.node,
                            properties
                        ]
                    ));
                }
            }
            
        }
    }
}
